package com.teradata.olingo.processor.core.serializer;

import com.teradata.olingo.processor.core.exception.ODataGenericSerializerException;
import org.apache.olingo.commons.api.data.Annotatable;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.EdmType;
import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.server.api.ODataRequest;
import org.apache.olingo.server.api.serializer.SerializerException;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.*;

import java.util.List;

final class GenericSerializeFunction implements GenericOperationSerializer {
  private final GenericOperationSerializer serializer;

  public GenericSerializeFunction(final UriInfo uriInfo, final ContentType responseFormat,
                                  final GenericSerializerFactory genericSerializerFactory) throws ODataGenericSerializerException, SerializerException {

    this.serializer = (GenericOperationSerializer) createSerializer(genericSerializerFactory, responseFormat, uriInfo);
  }

  @Override
  public SerializerResult serialize(final ODataRequest request, final EntityCollection result)
      throws SerializerException, ODataGenericSerializerException {
    return serializer.serialize(request, result);
  }

  @Override
  public SerializerResult serialize(final Annotatable annotatable, final EdmType entityType)
      throws SerializerException, ODataGenericSerializerException {
    return serializer.serialize(annotatable, entityType);
  }

  GenericSerializer getSerializer() {
    return serializer;
  }

  private GenericSerializer createSerializer(final GenericSerializerFactory genericSerializerFactory,
                                             final ContentType responseFormat,
                                             final UriInfo uriInfo) throws ODataGenericSerializerException, SerializerException {

    final List<UriResource> resourceParts = uriInfo.getUriResourceParts();
    final UriResourcePartTyped operation = (UriResourcePartTyped) resourceParts.get(resourceParts.size() - 1);
    final EdmTypeKind edmTypeKind = determineReturnEdmTypeKind(operation);
    return genericSerializerFactory.createSerializer(responseFormat, uriInfo, edmTypeKind, operation.isCollection());
  }

  private EdmTypeKind determineReturnEdmTypeKind(final UriResourcePartTyped operation) {
    if (operation instanceof UriResourceFunction)
      return ((UriResourceFunction) operation).getFunction().getReturnType().getType().getKind();
    else
      return ((UriResourceAction) operation).getAction().getReturnType().getType().getKind();
  }

  @Override
  public ContentType getContentType() {
    return this.serializer.getContentType();
  }

}
